package language_basic

import (
	"fmt"
	"reflect"
)

/**
面向对象世界中的接口的一般定义是“接口定义对象的行为”。它表示让指定  对象应该做什么 。实现这种行为的方法(实现细节)是针对对象的。
在Go中，接口是一组方法签名。当类型为接口中的所有方法提供定义时，它被称为实现接口。它与OOP非常相似。接口指定了类型应该具有的方法，类型决定了如何实现这些方法。
定义：
type interface_name interface {
   method_name1 [return_type]
   method_name2 [return_type]
   method_name3 [return_type]
   ...
   method_namen [return_type]
}

interface可以被任意的对象实现,一个对象可以实现任意多个interface.
任意的类型都实现了空interface(我们这样定义：interface{})，也就是包含0个method的interface
*/
type Book interface {
	writer()
	read()
}

type SheepskinBook interface {
	Book
	MatBottom()
}

type book struct {
	name string
}

type language struct {
	book
}
type english struct {
	book
}

func (Language language) writer() {
	fmt.Println(Language.name)
}
func (Language language) read() {
	fmt.Println(Language.name)
}
func (Language language) MatBottom() {
	fmt.Println(Language.name)
}

/**
interface{} 类型，空接口
空接口(interface{})不包含任何的方法，所有的类型都实现了空接口，因此空接口可以存储任意类型的数值。
*/
func Interface() {
	var str interface{} = "abc"

	retType, val := interfaceAssert1(str)
	fmt.Printf("type:%v, value:%v\n", retType, val)

	retType2, val2 := interfaceAssert2(str)
	fmt.Printf("type:%v, value:%v\n", retType2, val2)

	retType3 := interfaceAssert3(str)
	fmt.Printf("type:%v\n", retType3)
}

//直接断言
func interfaceAssert1(unknow interface{}) (retType string, val interface{}) {
	val, ok := unknow.(string)

	if ok {
		return "string", val
	} else {
		return "not string", nil
	}

}

//反射
func interfaceAssert2(unknow interface{}) (retType reflect.Type, val reflect.Value) {
	retType = reflect.TypeOf(unknow)
	val = reflect.ValueOf(unknow)
	return retType, val
}

//type关键字
func interfaceAssert3(unknow interface{}) (retType string) {
	switch unknow.(type) {
	case string:
		return "string"
	case int:
		return "int"
	default:
		return "other type"
	}
}
